package com.ssm.user.designPattern.responseibilityChainPattern;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

@Component
@Slf4j
public class RuleCheckCompont {

    public RuleCheckResult checkResult(ArticleInfo articleInfo) {
        RuleCheckContext ruleCheckContext = new RuleCheckContext();
        //this代表当前类，加不加都一样
        return this.checkTitle(articleInfo)
                .andThen(this.checkContentLength(articleInfo)) //andThen，当前结果接着传递给下一个方法使用，可使RuleCheckContext对象共享，调用hasError方法时，会按照该类的成员属性创建一个Result对象
                .apply(ruleCheckContext) //传入T,返回R，此时上一个链返回的对象为Function<T,T>，所以传入RuleCheckContext，返回类型也一样
                .getRuleCheckResult();
    }

    /**
     * 检验文章标题不能包含中国
     *
     */
    private Function<RuleCheckContext, RuleCheckContext> checkTitle(ArticleInfo articleInfo) {
//        return buildCheck(new Consumer<RuleCheckContext>() { //消费模型的T和Function的T，R都一样
//            @Override
//            public void accept(RuleCheckContext ruleCheckContext) {
//                if(ruleCheckContext.hasError()) { //如果当前失败列表有值，则直接返回，不往下传递
//                    return; //该return返回的是accept消费模型的无返回值的方法
//                }
//                String title = articleInfo.getTitle();
//                if(title.contains("中国")) {
//                    RuleCheckCompont.this.addFailedMsg(ruleCheckContext.getRuleCheckResult(), "标题不能包含中国");
//                }
//            }
//        });
        return buildCheck(titleArticle -> {
            if(titleArticle.hasError()) {
                return;
            }
            String title = articleInfo.getTitle();
            if(title.contains("中国")) {
                RuleCheckCompont.this.addFailedMsg(titleArticle.getRuleCheckResult(), "标题不能包含中国");
            }
        });
    }

    /**
     * 检查内容长度
     */
    private Function<RuleCheckContext, RuleCheckContext> checkContentLength(ArticleInfo articleInfo) {
        return buildCheck(new Consumer<RuleCheckContext>() {
            @Override
            public void accept(RuleCheckContext ruleCheckContext) {
                if(ruleCheckContext.hasError()) {
                    return;
                }
                String content = articleInfo.getContent();
                if(content.length() > 10) {
                    addFailedMsg(ruleCheckContext.getRuleCheckResult(), "内容长度不能大于10");
                }
            }
        });
    }


    /**
     * 添加失败的信息
     */
    private void addFailedMsg(RuleCheckResult ruleCheckResult, String message) {
        List<String> failedMsgList = ruleCheckResult.getFailedMsgList();
        if(failedMsgList == null) {
            failedMsgList = new ArrayList<>();
            ruleCheckResult.setFailedMsgList(failedMsgList);
        }
        failedMsgList.add(message);
    }

    /**
     * buildCheck可直接返回Function接口，返回该接口需要创建匿名内部类，重写apply方法(该方法可进行类型转换，把T转为R)，但这里TR都一样，
     * 函数内部，根据消费模型consumer接口进行消费，该接口内部的accept方法无返回值。
     */
    private <T> Function<T, T> buildCheck(Consumer<T> consumer) {
//        return new Function<T, T>() {
//            @Override
//            public T apply(T t) { //apply有返回值，所以最后返回R，也就是t
//                consumer.accept(t); //Consumer的accept方法无返回值，后面调用该方法的函数重写accept方法进行执行。
//                return t;
//            }
//        };
        return t -> {
            consumer.accept(t);
            return t;
        };
    }
}
